package com.ali.ttt.controller;

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @Author : yuxl
 * @create 2024/8/2 4:05 PM
 */
@Slf4j
@RestController
@RequestMapping("/api/cas")
@Api(tags = "cas操作")
@AllArgsConstructor
public class CASController {

    @GetMapping("/add")
    @ApiOperation(value = "计算百万相加")
    public Integer add() throws ExecutionException, InterruptedException {
        AtomicInteger count = new AtomicInteger(0);
        CompletableFuture<Void> c1 = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 1000000; i++) {
                count.addAndGet(-1);
            }
        });
        CompletableFuture<Void> c2 = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 1000000; i++) {
                count.addAndGet(-1);
            }
        });
        CompletableFuture<Void> c3 = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 1000000; i++) {
                count.addAndGet(-1);
            }
        });
        CompletableFuture<Void> c4 = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 1000000; i++) {
                count.addAndGet(-1);
            }
        });
        CompletableFuture<Void> c5 = CompletableFuture.runAsync(() -> {
            for (int i = 0; i < 1000000; i++) {
                count.addAndGet(-1);
            }
        });
        CompletableFuture.allOf(c1,c2,c3,c4,c5).get();
        return count.get();
    }

    @GetMapping("/add2")
    @ApiOperation(value = "计算百万相加2")
    public Integer add2() throws ExecutionException, InterruptedException {
        JSONObject user = new JSONObject();
        user.put("money",0);
        AtomicStampedReference<JSONObject> u = new AtomicStampedReference<>(user,0);
        AtomicInteger v = new AtomicInteger(0);
        return u.getReference().getIntValue("money");
    }

    @GetMapping("/compareAdd")
    @ApiOperation(value = "单线程计算百万相加")
    public Integer compareAdd() throws ExecutionException, InterruptedException {
        return CompletableFuture.supplyAsync(() -> {
            int n = 0;
            for (int i = 0; i < 5000000; i++) {
                n++;
            }
            return n;
        }).get();
    }

    @GetMapping("/compareAdd2")
    @ApiOperation(value = "单线程计算百万相加2")
    public Integer compareAdd2() throws ExecutionException, InterruptedException {
        return CompletableFuture.supplyAsync(() -> {
            JSONObject user = new JSONObject();
            user.put("money",0);
            AtomicStampedReference<JSONObject> u = new AtomicStampedReference<>(user,0);
            for (int i = 0; i < 5000000; i++) {
                int expectedStamp = u.getStamp();
                int newStamp = expectedStamp+1;
                JSONObject expectedReference = u.getReference();
                JSONObject newReference = new JSONObject();
                newReference.put("money",expectedReference.getIntValue("money")+1);
                u.compareAndSet(expectedReference,newReference,expectedStamp,newStamp);
            }
            return u.getReference().getInteger("money");
        }).get();
    }
}
